<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * 商品分类管理
 * 
 * @author  : $Author: spike $
 * @date    : $Date: 2014-03-03 09:31:20 +0800 (一, 2014-03-03) $
 * @version : $Id: category_model.php 39 2014-03-03 01:31:20Z spike $
 * @rev     : $Revision: 39 $
 */
class Category_model extends CI_Model
{
    static private $_max_depth;

    public function __construct()
    {
        parent::__construct();

        self::$_max_depth = CATEGORY_MAX_DEPTH;
    }    

    // --------------------------------------------------------------------
    
    /**
     * [获得一个分类]
     * @param  [int]        $category_id
     * @param  [bool]       $enable        [是否排除"关闭状态"]
     * @return [array/false]
     */
    public function get_category($category_id, $enable = TRUE)
    {
        if( ! validate($category_id, 'category_id') )
        {
            $this->set_error("获取分类失败：分类ID[{$category_id}]格式不正确。");
            return FALSE;
        }
        
        $where = array(
            'category_id' => $category_id,
            'is_delete'   => UNDELETED,
        );
        if($enable === TRUE)
        {
            $where['status'] = CATEGORY_STATUS_ON;
        }

        $this->load->dao('Category_dao');
        $category = $this->Category_dao->get_one($where);
        if( ! $category)
        {
            $this->set_error("获取分类失败：无法找到分类[{$category_id}]。");
            return FALSE;
        }

        return $category;
    }
    
    /**
     * [获得指定层级深度内的所有分类]
     * @param  [int]    $depth  [最大层级，最小1]
     * @param  [bool]   $enable [是否排除"关闭状态"]
     * @return [array] 
     */
    public function get_category_by_depth($depth, $enable = TRUE)
    {
        $depth = (int)$depth;
        $depth = max(1, $depth);
        $depth = min($depth, self::$_max_depth);

        $category = array();

        $where = array(
            'depth <='  => $depth,
            'is_delete' => UNDELETED,
        );
        if($enable === TRUE)
        {
            $where['status'] = CATEGORY_STATUS_ON;
        }
        $this->load->dao('Category_dao');
        $result = $this->Category_dao->get(
            $where,
            array('category_id','name','seo_name','depth','parent_id','status'),
            '`depth` ASC, `sort` ASC'
        );

        $category = array();
        foreach($result as $r)
        {
            $category[$r['depth']][$r['category_id']] = $r;
        }
        while($depth>=1)
        {
            // 最底层 结束
            if($depth === 1)
            {
                $category = $category[1];
                break;
            }
            if($category[$depth])
            {
                // 移入上一层
                foreach ($category[$depth] as $t)
                {
                    $cid = $t['category_id'];
                    $pid = $t['parent_id'];
                    if( isset($category[$depth-1][$pid]) )
                    {
                        $category[$depth-1][$pid]['children'][$cid] = $t;
                    }
                }
            }
            unset($category[$depth]);
            $depth--;
        }

        return $category;
    }

    // --------------------------------------------------------------------
    
    /**
     * [改变状态]
     * 
     * @param  [int]    $category_id   [编码]
     * @param  [string] $act        [操作类型]
     * @return [bool]
     */
    public function change_category_status($category_id, $act)
    {   
        if( ! $category = $this->get_category($category_id, FALSE))
        {
            $this->set_error("修改分类状态失败：无法找到分类[{$category_id}]。");
            return FALSE;
        }

        // 初始化数据
        $_status       = NULL;  //修改的状态
        $_allow_status = NULL;  //允许修改的状态
        $_update       = NULL;  //更新的数据
        
        switch (strtolower(trim($act)))
        {
            case 'on':
                    $_status       = CATEGORY_STATUS_ON;
                    $_allow_status = array(CATEGORY_STATUS_OFF);
                    $_update       = array(
                        'status'       => $_status,
                        'update_time'  => now_str(),
                        'update_admin' => login_info('admin_id'), 
                    );
                break;

            case 'off':
                    $_status       = CATEGORY_STATUS_OFF;
                    $_allow_status = array(CATEGORY_STATUS_ON);
                    $_update       = array(
                        'status'       => $_status,
                        'update_time'  => now_str(),
                        'update_admin' => login_info('admin_id'), 
                    );
                break;

            default:
                    $this->set_error("修改分类状态失败：未知的操作[{$act}]。");
                    return FALSE;
                break;
        }

        $status      = $this->config->item('category_status');
        $status_name = (string)$status[$_status];

        // 验证状态
        $current_status = (int)$category['status'];
        if($current_status === $_status)
        {
            $this->set_error("修改分类状态失败：无需修改。");
            return FALSE;
        }

        if( $_allow_status && ! in_array($current_status, $_allow_status))
        {
            $this->set_error("修改分类状态失败：不允许被修改为[{$status_name}]状态。");
            return FALSE;
        }

       
        // 只有符合条件才会被修改
        $this->load->dao('Category_dao');
        $affected_row = $this->Category_dao->update_in(
            $_update,
            array('status'      => $_allow_status),
            array('category_id' => $category_id)
        );
        if($affected_row<=0)
        {
            $this->set_error("修改分类状态失败：无法写入数据库。");
            return FALSE;
        }

        return TRUE;
    }

    // --------------------------------------------------------------------
    
    /**
     * [新增分类]
     * @param  [array]  $params [所有信息的数组]
     * @return [bool]
     */
    public function add_category(Array $params)
    {
        $params = array(
            'name'          => isset($params['name'])          ? xss_clean(trim($params['name']))         : NULL,
            'seo_name'      => isset($params['seo_name'])      ? xss_clean(trim($params['seo_name']))     : NULL,
            'parent_id'     => isset($params['parent_id'])     ? (int)$params['parent_id']                : NULL,
            'attr_group_id' => isset($params['attr_group_id']) ? xss_clean(trim($params['attr_group_id'])): NULL,
        );
        
        $category = array();

        /* 验证名称开始 */
        if( ! validate_length($params['name'], 1, 20) )
        {
            $this->set_error("新增分类失败：分类名最少1个字最多20个字。[{$params['name']}]");
            return FALSE;
        }
        $this->load->dao('Category_dao');
        $count = $this->Category_dao->count(array(
            'name'      => $params['name'],
            'is_delete' => UNDELETED,
        ));
        if( $count > 0 )
        {
            $this->set_error("新增分类失败：分类名已存在。[{$params['name']}]");
            return FALSE;
        }
        $category['name'] = $params['name'];
        /* 验证名称结束 */

        /* 验证SEO名称开始 */
        if( ! preg_match('/^[\d|\w]{1,20}$/', $params['seo_name']) )
        {
            $this->set_error("新增分类失败：分类SEO名必须为英文或数字，最多20个字。");
            return FALSE;
        }
        $this->load->dao('Category_dao');
        $count = $this->Category_dao->count(array(
            'seo_name'  => $params['seo_name'],
            'is_delete' => UNDELETED,
        ));
        if( $count > 0 )
        {
            $this->set_error("新增分类失败：分类SEO名已存在。[{$params['name']}]");
            return FALSE;
        }
        $category['seo_name'] = $params['seo_name'];
        /* 验证SEO名称结束 */

        /* 验证属性模版开始 */
        if( ! validate($params['attr_group_id'], 'ATTR_GROUP_ID') )
        {
            $this->set_error("新增分类失败：必须指定一个属性模版。[{$params['attr_group_id']}]");
            return FALSE;
        }

        $this->load->dao('Attr_group_dao');
        $count = $this->Attr_group_dao->count(array(
            'status'        => ATTR_GROUP_STATUS_ON,
            'is_delete'     => UNDELETED,
            'attr_group_id' => $params['attr_group_id']
        ));

        if( $count <= 0 )
        {
            $this->set_error("新增分类失败：无法找到属性模版。[{$params['attr_group_id']}]");
            return FALSE;
        }
        $category['attr_group_id'] = $params['attr_group_id'];
        /* 验证属性模版结束 */

        /* 验证父辈id开始 */
        if($params['parent_id'] === 0)
        {
            $category['parent_id'] = 0;
            $category['depth']     = 1;
        }
        else
        {
            $this->load->dao('Category_dao');
            $cat = $this->Category_dao->get_one(array(
                'is_delete'   => UNDELETED,
                'category_id' => $params['parent_id'],
            ));
            if( ! $cat )
            {
                $this->set_error("新增分类失败：指定的所属分类[id={$params['parent_id']}]不存在。");
                return FALSE;
            }
            $depth = (int)$cat['depth']+1;
            if($depth > self::$_max_depth)
            {
                $this->set_error("新增分类失败：最多只能支持".self::$_max_depth."级分类。");
                return FALSE;
            }
            $category['parent_id'] = $params['parent_id'];
            $category['depth']     = $depth;
        }
        /* 验证父辈id结束 */
        
        // 写入
        $category['status']       = CATEGORY_STATUS_ON;
        $category['is_delete']    = UNDELETED;
        $category['create_admin'] = login_info('admin_id');
        $category['create_time']  = now_str();

        $this->load->dao('Category_dao');
        if( FALSE === $category_id = $this->Category_dao->insert($category))
        {
            $this->set_error("新增分类失败：无法写入数据库。");
            return FALSE;
        }

        return $category_id;
    }

    // --------------------------------------------------------------------
    
    /**
     * [编辑分类]
     * @param  [int]    $category_id    [分类id]
     * @param  [array]  $params         [所有信息的数组]
     * @return [bool]
     */
    public function edit_category($category_id, Array $params)
    {
        if( FALSE === $this->get_category($category_id, TRUE) )
        {
            $this->set_error("编辑分类失败：无法找到分类[{$category_id}]。");
            return FALSE;
        }

        $params = array(
            'name'          => isset($params['name'])          ? xss_clean(trim($params['name']))          : NULL,
            'seo_name'      => isset($params['seo_name'])      ? xss_clean(trim($params['seo_name']))      : NULL,
            'attr_group_id' => isset($params['attr_group_id']) ? xss_clean(trim($params['attr_group_id'])) : NULL,
        );

        $category = array();

        /* 验证名称开始 */
        if( isset($params['name']) )
        {
            if( ! validate_length($params['name'], 1, 20) )
            {
                $this->set_error("编辑分类失败：分类名最少1个字最多20个字[{$params['name']}]。");
                return FALSE;
            }
            $this->load->dao('Category_dao');
            $count = $this->Category_dao->count(array(
                'name'           => $params['name'],
                'category_id <>' => $category_id,
                'is_delete'      => UNDELETED,
            ));
            if( $count > 0 )
            {
                $this->set_error("编辑分类失败：分类名[{$params['name']}]已存在。");
                return FALSE;
            }
            $category['name'] = $params['name'];
        }
        /* 验证名称结束 */

        /* 验证SEO名称开始 */
        if( isset($params['seo_name']) )
        {
            if( ! preg_match('/^[\d|\w]{1,20}$/', $params['seo_name']) )
            {
                $this->set_error("编辑分类失败：分类SEO名必须为英文或数字，最多20个字。");
                return FALSE;
            }
            $this->load->dao('Category_dao');
            $count = $this->Category_dao->count(array(
                'seo_name'       => $params['seo_name'],
                'category_id <>' => $category_id,
                'is_delete'      => UNDELETED,
            ));
            if( $count > 0 )
            {
                $this->set_error("编辑分类失败：分类SEO名[{$params['name']}]已存在。");
                return FALSE;
            }
            $category['seo_name'] = $params['seo_name'];
        }
        /* 验证SEO名称结束 */

        /* 验证属性模版开始 */
        if( isset($params['attr_group_id']) )
        {
            if( ! validate($params['attr_group_id'], 'ATTR_GROUP_ID') )
            {
                $this->set_error("新增分类失败：必须指定一个属性模版。[{$params['attr_group_id']}]");
                return FALSE;
            }

            $this->load->dao('Attr_group_dao');
            $count = $this->Attr_group_dao->count(array(
                'status'        => ATTR_GROUP_STATUS_ON,
                'is_delete'     => UNDELETED,
                'attr_group_id' => $params['attr_group_id']
            ));

            if( $count <= 0 )
            {
                $this->set_error("新增分类失败：无法找到属性模版。[{$params['attr_group_id']}]");
                return FALSE;
            }
            $category['attr_group_id'] = $params['attr_group_id'];
        }
        /* 验证属性模版结束 */
        
        if( ! $category )
        {
            $this->set_error("编辑分类失败：没有需要编辑的内容。");
            return FALSE;
        }

        // 编辑
        $category['update_admin'] = login_info('admin_id');
        $category['update_time']  = now_str();

        $where['category_id'] = $category_id; 
        $where['status']      = CATEGORY_STATUS_ON; 
        $where['is_delete']   = UNDELETED;

        $this->load->dao('Category_dao');
        $count = $this->Category_dao->update(
            $category,
            $where,
            NULL,
            1
        );
        if( ! ($count > 0) )
        {
            $this->set_error("编辑分类失败：无法写入数据库。");
            return FALSE;
        }

        return TRUE;
    }

    /**
     * [批量编辑分类]
     * @param  [int]    $category_id    [分类id]
     * @param  [array]  $params         [所有信息的数组]
     * @return [bool]
     */
    public function batch_edit_category($categorys)
    {
        if( ! is_array($categorys) || ! $categorys)
        {
            $this->set_error("批量编辑分类失败：请提供正确的参数。");
            return FALSE;
        }

        $data = array();
        $sort = 1;

        $update_time  = now_str();
        $update_admin = login_info('admin_id');
        foreach($categorys as $c)
        {
            if( ! validate($c['id'], 'category_id') )
            {
                $this->set_error("批量编辑分类失败：[{$c['id']}]不是一个正确的分类ID。");
                return FALSE;
            }
            $data[] = array(
                'category_id'  => $c['id'],
                'depth'        => 1,
                'parent_id'    => 0,
                'sort'         => $sort,
                'update_time'  => & $update_time,
                'update_admin' => & $update_admin,
            );

            if( is_array($c['children']) )
            {
                $csort = 1;
                foreach($c['children'] as $child)
                {
                    if( ! validate($child['id'], 'category_id') )
                    {
                        $this->set_error("批量编辑分类失败：[{$child['id']}]不是一个正确的分类ID。");
                        return FALSE;
                    }
                    $data[] = array(
                        'category_id'  => $child['id'],
                        'depth'        => 2,
                        'parent_id'    => $c['id'],
                        'sort'         => $csort,
                        'update_time'  => & $update_time,
                        'update_admin' => & $update_admin,
                    );
                    $csort++;
                }
            }
            $sort++;
        }

        $this->load->dao('Category_dao');
        $this->Category_dao->update_batch($data, 'category_id');

        return TRUE;   
    }

    // --------------------------------------------------------------------

    /**
     * [绑定分类信息]
     * @param  [& array]    列表, 必须包含brand_sn
     * @param  [bool]       是否开启单个模式
     * @param  [string]     列表中`brand_sn`列的键名
     * @return [bool]
     */
    public function wrap_category_info( & $list, $single_mode = FALSE, $key = 'category_id')
    {
        if( ! $list || ! $key ) 
            return FALSE;
        
        switch ($key) 
        {
            case 'category_id':
                $col = 'category_id';
                break;

            default:
                return FALSE;
                break;
        }

        if($single_mode === TRUE)
        {
            $sn = $list[$key];
            if( ! $sn) 
                return FALSE;

            $this->load->dao('Category_dao');
            $category = $this->Category_dao->get_one(
                array(
                    'is_delete'   => UNDELETED,
                    'category_id' => $sn,
                ),
                array(
                    'category_id','name','seo_name'
                )
            );
            $list['category_info'] = $category;
        }
        else
        {
            $sns = array_pick($list, $key);
            if( ! $sns) 
                return FALSE;
            
            // 获取角色信息
            $this->load->dao("Category_dao");    
            $category = $this->Category_dao->get_in(
                array('category_id' => $sns),
                array('is_delete' => UNDELETED), 
                array('category_id','name','seo_name')
            );

            array_change_key($category, 'category_id');

            foreach ($list as &$item) 
            {
                $sn                    = $item[$key];
                $item['category_info'] = isset($category[$sn]) ? $category[$sn] : array();
            }
            unset($item);
        }
        
        unset($list);
        return TRUE;
    }
 }
